﻿using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Threading;

namespace PLinq
{

    class Program
    {
        static void Main(string[] args)
        {
            var nums = Enumerable.Range(1, 20);


            ParallelQuery<int> result = nums.AsParallel();

            ParallelQuery<int> resultParallel = 
                result
                    .WithDegreeOfParallelism(5)
                    .Select(num => { Thread.Sleep(new Random().Next(1000)); return num; });

            WriteExampleHeading("Exemplo - Parallel Linq");

            resultParallel.ForAll(num =>
            { Thread.Sleep(new Random().Next(1000)); WriteObject(num); }
                );


            WriteExampleHeading("Exemplo - Parallel Linq - MergeOptions - Non Buffered");

            foreach (int num in resultParallel.WithMergeOptions(ParallelMergeOptions.NotBuffered))
            {
                WriteObject(num);
            }

            WriteExampleHeading("Exemplo - Parallel Linq - MergeOptions - AutoBuffered");

            foreach (int num in resultParallel.WithMergeOptions(ParallelMergeOptions.NotBuffered))
            {
                WriteObject(num);
            }

            WriteExampleHeading("Exemplo - Parallel Linq - MergeOptions - FullyBuffered");

            foreach (int num in resultParallel.WithMergeOptions(ParallelMergeOptions.FullyBuffered))
            {
                WriteObject(num);
            }


            WriteExampleHeading("Exemplo - Parallel Linq Com Order By");

            OrderedParallelQuery<int> ordParQuery = resultParallel.OrderByDescending(T => T);
            foreach (int num in ordParQuery)
            {
                WriteObject(num);
            }


            Console.ReadLine();
        }


        #region Helper Methods

        private static void WriteExampleHeading(string descricaoExemplo)
        {
            if (first)
                first = false;
            else
                Console.WriteLine(Environment.NewLine);
            Console.WriteLine(descricaoExemplo + Environment.NewLine);
        }
        private static void WriteResult<T>(IEnumerable<T> resultados)
        {
            foreach (T resultado in resultados)
            {
                WriteObject(resultado);
            }
        }
        private static void WriteObject(object objectToWrite)
        {
            //Bar obj = objectToWrite as Bar;
            //if (obj != null)
            //{
            //    Console.WriteLine("Id = " + obj.Id + ", Nome = " + obj.Nome + ", Localidade = " + obj.Localidade + ", Entrada = " + obj.Entrada);
            //    return;
            //}

            //Bebida obj2 = objectToWrite as Bebida;
            //if (obj2 != null)
            //{
            //    Console.WriteLine("Id = " + obj2.Id + ", BarId = " + obj2.IdBar + ", Nome = " + obj2.Nome + ", Preço = " + obj2.Preco);
            //    return;
            //}

            Console.WriteLine(objectToWrite.ToString());
        }

        static bool first = true;

        #endregion
    }
}
